;; URL: https://github.com/justbur/which-key/
;; Version: 0.1
;; Keywords:
-;; Package-Requires: ((s "1.9.0") (popwin "1.0.0"))
+;; Package-Requires: ((emacs "24.3") (s "1.9.0") (popwin "1.0.0"))
;;; Commentary:
;;
(defvar which-key-side-window-max-height 20
"Maximum height of which-key popup when type is side-window and
location is top or bottom.")
+(defvar which-key-frame-max-width 60
+ "Maximum width of which-key popup when type is frame.")
+(defvar which-key-frame-max-height 20
+ "Maximum height of which-key popup when type is frame.")
;; (defvar which-key-display-method 'minibuffer
;; "Controls the method used to display the keys. The default is
;; minibuffer, but other possibilities are 'popwin and
"Internal: Holds reference to close window timer.")
(defvar which-key--setup-p nil
"Internal: Non-nil if which-key buffer has been setup.")
+(defvar which-key--frame nil
+ "Internal: Holds reference to which-key frame.
+Used when `which-key-popup-type' is 'popup.")
;;;###autoload
(define-minor-mode which-key-mode
(which-key/start-open-timer))
(remove-hook 'focus-out-hook 'which-key/stop-open-timer)
(remove-hook 'focus-in-hook 'which-key/start-open-timer)
- (which-key/stop-open-timer)))
+ (which-key/stop-open-timer)
+ (which-key/stop-close-timer)))
(defun which-key/setup ()
"Create buffer for which-key."
(if (> (length key) 0)
(progn
(which-key/stop-close-timer)
- (which-key/hide-popup)
+ ;; remove this because `which-key/show-popup' should be able to
+ ;; handle the case where which-key buffer is already displayed
+ ;; (which-key/hide-popup)
(let* ((buf (current-buffer))
;; get formatted key bindings
(fmt-width-cons (which-key/get-formatted-key-bindings buf key))
;; (delete-window which-key--window)))
(defun which-key/hide-popup ()
+ (cl-case which-key-popup-type
+ (minibuffer (which-key/hide-buffer-minibuffer))
+ (side-window (which-key/hide-buffer-side-window))
+ (frame (which-key/hide-buffer-frame))))
+
+(defun which-key/hide-buffer-minibuffer ()
+ nil)
+
+(defun which-key/hide-buffer-side-window ()
(when (buffer-live-p which-key--buffer)
- (delete-windows-on which-key--buffer)))
+ ;; in case which-key buffer was shown in an existing window, `quit-window'
+ ;; will re-show the previous buffer, instead of closing the window
+ (quit-windows-on which-key--buffer)))
+
+(defun which-key/hide-buffer-frame ()
+ (when (frame-live-p which-key--frame)
+ (delete-frame which-key--frame)))
(defun which-key/show-popup (act-popup-dim)
"Show guide window. ACT-POPUP-DIM includes the
need to start the closing timer."
(cl-case which-key-popup-type
(minibuffer (which-key/show-buffer-minibuffer act-popup-dim))
- (side-window (which-key/show-buffer-side-window act-popup-dim))))
+ (side-window (which-key/show-buffer-side-window act-popup-dim))
+ (frame (which-key/show-buffer-frame act-popup-dim))))
(defun which-key/show-buffer-minibuffer (act-popup-dim)
nil)
(let* ((height (car act-popup-dim))
(width (cdr act-popup-dim))
(side which-key-side-window-location)
- (alist (delq nil (list (when side (cons 'side side))
- (when height (cons 'window-height height))
+ (alist (delq nil (list (when height (cons 'window-height height))
(when width (cons 'window-width width))))))
- (display-buffer which-key--buffer (cons 'display-buffer-in-side-window alist))))
+ ;; Note: `display-buffer-in-side-window' and `display-buffer-in-major-side-window'
+ ;; were added in Emacs 24.3
+
+ ;; If two side windows exist in the same side, `display-buffer-in-side-window'
+ ;; will use on of them, which isn't desirable. `display-buffer-in-major-side-window'
+ ;; will pop a new window, so we use that.
+ ;; +-------------------------+ +-------------------------+
+ ;; | regular window | | regular window |
+ ;; | | +------------+------------+
+ ;; +------------+------------+ --> | side-win 1 | side-win 2 |
+ ;; | side-win 1 | side-win 2 | |------------+------------|
+ ;; | | | | which-key window |
+ ;; +------------+------------+ +------------+------------+
+ ;; (display-buffer which-key--buffer (cons 'display-buffer-in-side-window alist))
+ ;; side defaults to bottom
+ (if (get-buffer-window which-key--buffer)
+ (display-buffer-reuse-window which-key--buffer alist)
+ (display-buffer-in-major-side-window which-key--buffer side 0 alist))))
+
+(defun which-key/show-buffer-frame (act-popup-dim)
+ (let ((orig-window (selected-window))
+ (new-window (if (and (frame-live-p which-key--frame)
+ (eq which-key--buffer
+ (window-buffer (frame-root-window which-key--frame))))
+ (which-key/show-buffer-reuse-frame)
+ (which-key/show-buffer-new-frame act-popup-dim))))
+ (fit-frame-to-buffer (window-frame new-window))
+ (select-frame-set-input-focus (window-frame orig-window))
+ (select-window orig-window)
+ (setq which-key--frame (window-frame new-window))
+ new-window))
+
+(defun which-key/show-buffer-new-frame (act-popup-dim)
+ (let* ((height (car act-popup-dim))
+ (width (cdr act-popup-dim))
+ (frame-params (delq nil (list (when (and height width) (cons 'window-height height))
+ (when (and height width) (cons 'window-width width))
+ (cons 'minibuffer nil)
+ (cons 'name "which-key"))))
+ (alist (list (cons 'pop-up-frame-parameters frame-params)
+ (cons 'inhibit-switch-frame t))))
+ (display-buffer-pop-up-frame which-key--buffer alist)))
+
+(defun which-key/show-buffer-reuse-frame ()
+ (display-buffer-reuse-window which-key--buffer `((reusable-frames . ,which-key--frame))))
;; Keep for popwin maybe (Used to work)
;; (defun which-key/show-buffer-popwin (height width)
of the intended popup."
(cl-case which-key-popup-type
(minibuffer (which-key/minibuffer-max-dimensions))
- (side-window (which-key/side-window-max-dimensions column-width))))
+ (side-window (which-key/side-window-max-dimensions column-width))
+ (frame (which-key/frame-max-dimensions))))
(defun which-key/minibuffer-max-dimensions ()
(cons
(min which-key-side-window-max-width column-width)
(frame-width))))
+(defun which-key/frame-max-dimensions ()
+ (cons which-key-frame-max-height which-key-frame-max-width))
+
;; Buffer contents functions
(defun which-key/get-formatted-key-bindings (buffer key)
(if (eq which-key-popup-type 'minibuffer)
(let (message-log-max) (message "%s" (car pages)))
(with-current-buffer which-key--buffer
- (insert (car pages)))))
+ (erase-buffer)
+ (insert (car pages))
+ (goto-char (point-min)))))
(cons act-height act-width)))
(defun which-key/replace-strings-from-alist (replacements)